package androidx.gdata.spreadsheets;

import org.w3c.dom.Node;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;

import android.util.Log;
import androidx.gdata.GDataServer;
import androidx.gdata.LinkUrl;
import androidx.gdata.ThingWithLinks;
import androidx.gdata.spreadsheets.xml.ListCollectionDeserializer;
import androidx.gdata.spreadsheets.xml.ListEntryDeserializer;
import androidx.gdata.spreadsheets.xml.ListEntrySerializer;
import androidx.gdata.spreadsheets.xml.SpreadsheetCollectionDeserializer;
import androidx.gdata.spreadsheets.xml.WorksheetCollectionDeserializer;

public class SpreadsheetsServerImpl extends GDataServer implements SpreadsheetsServer {

  private static final String WORKSHEETS_FEED =
    "http://schemas.google.com/spreadsheets/2006#worksheetsfeed";
  private static final String LIST_FEED =
    "http://schemas.google.com/spreadsheets/2006#listfeed";
  
  private URL url;
  private static ListEntrySerializer entrySerializer =
    new ListEntrySerializer();
  private static SpreadsheetCollectionDeserializer
    spreadsheetCollectionDeserializer = new SpreadsheetCollectionDeserializer();
  private static WorksheetCollectionDeserializer
    worksheetCollectionDeserializer = new WorksheetCollectionDeserializer();
  private static ListCollectionDeserializer
    listCollectionDeserializer = new ListCollectionDeserializer();
  private static ListEntryDeserializer
    listEntryDeserializer = new ListEntryDeserializer();
  
  protected SpreadsheetsServerImpl(String baseUrl, String username, String auth) {
    super(baseUrl, username, auth);
    try {
      url = new URL(baseUrl);
    } catch (MalformedURLException e) {
      throw new RuntimeException("Bad URL!", e);
    }
  }

  public SpreadsheetCollection getSpreadsheetCollection() throws IOException {
    String result = doAuthorizedGet(url);
    Log.i("Notes", "fetch result = " + result);
    Node feedNode = extractFeedNode(result);
    return spreadsheetCollectionDeserializer.build(feedNode);
  }
  
  public WorksheetCollection getWorksheetCollection(ThingWithLinks spreadsheet)
    throws MalformedURLException, IOException {
    LinkUrl[] links = spreadsheet.getLinks();
    for (int i = 0; i < links.length; i++) {
      if (links[i].getRel().equals(WORKSHEETS_FEED)) {
        String result = doAuthorizedGet(new URL(links[i].getHref()));
        Log.i("Notes", "fetch result = " + result);
        Node feedNode = extractFeedNode(result);
        return worksheetCollectionDeserializer.build(feedNode);
      }
    }
    return null;
  }
  
  public ListCollection getListCollection(Worksheet worksheet)
    throws MalformedURLException, IOException {
    LinkUrl[] links = worksheet.getLinks();
    for (int i = 0; i < links.length; i++) {
      if (links[i].getRel().equals(LIST_FEED)) {
        String result = doAuthorizedGet(new URL(links[i].getHref()));
        Log.i("Notes", "fetch result = " + result);
        Node feedNode = extractFeedNode(result);
        return listCollectionDeserializer.build(feedNode);
      }
    }
    return null;
  }
  
  public ListEntry postListEntry(String postUrl, ListEntry entry)
    throws IOException {
    StringWriter sw = new StringWriter();
    PrintWriter out = new PrintWriter(sw);
    entrySerializer.serialize(out, entry);
    out.flush();
    URL url = new URL(postUrl);
    String atomPost = sw.toString();
    String rv = doAtomPost(url, atomPost);
    Log.i("Notes", "Post response " + rv);
    Node entryNode = extractEntryNode(rv);
    return listEntryDeserializer.build(entryNode);
  }
  
  public ListEntry putListEntry(String editUrl, ListEntry entry)
    throws IOException {
    StringWriter sw = new StringWriter();
    PrintWriter out = new PrintWriter(sw);
    entrySerializer.serialize(out, entry);
    out.flush();
    URL url = new URL(editUrl);
    String atomPut = sw.toString();
    String rv = doAtomPut(url, atomPut);
    Log.i("Notes", "Put response " + rv);
    Node entryNode = extractEntryNode(rv);
    return listEntryDeserializer.build(entryNode);
  }
}
